//
//  YMHomeCycleScrollView.m
//  YMMedical
//
//  Created by y s on 2023/7/19.
//

#import "YMHomeCycleScrollView.h"
#import "YMHomeHealthMoreItemCell.h"
#import "YMHomeCycleFlowLayout.h"

#define DRAG_DISPLACEMENT_THRESHOLD 20

static NSString *cellIdentifier = @"YMHomeHealthMoreItemCell";

@interface YMHomeCycleScrollView ()<UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>

@property (nonatomic, strong) UICollectionView *cvMain;
@property (nonatomic, strong) YMHomeCycleFlowLayout *layout;
@property (nonatomic, assign) CGFloat pageWidth; /**< CollectionView PageWidth */
@property (nonatomic, assign) CGFloat pageHeight; /**< CollectionView PageHeight */
@property (nonatomic, assign) BOOL snapping;
@property (nonatomic, assign) CGPoint dragVelocity;
@property (nonatomic, assign) CGPoint dragDisplacement;
@property (nonatomic, assign) BOOL pageEnable;

@property (nonatomic, strong) NSMutableArray *arrResult;

@end

@implementation YMHomeCycleScrollView

+ (instancetype)cardViewWithFrame:(CGRect)frame dataSource:(NSArray *)dataSource {
    
    YMHomeCycleScrollView *cardView = [[self alloc] initWithFrame:frame];
    cardView.dataSource = dataSource;
    return cardView;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.pageEnable = YES;
        [self setupUI];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetContentOffset) name:@"ResetContentOffset" object:nil];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    // 在一开始的时候设置 CollectionView 的偏移位置
    [self resetContentOffset];
}

#pragma mark - UI
- (void)setupUI {
    [self addSubview:self.cvMain];
    [self.cvMain mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self);
    }];
}

#pragma mark - Custom Accessors
/**传入数据源,设置数据源*/
- (void)setDataSource:(NSArray *)dataSource {
    _dataSource = dataSource;
    if (self.arrResult.count > 0){
        [self.arrResult removeAllObjects];
    }
    if (dataSource.count != 1) {
        self.cvMain.scrollEnabled = YES;
    } else {
        self.cvMain.scrollEnabled = NO;
    }
    if (dataSource.count > 0){
        [self.arrResult addObjectsFromArray:dataSource];
        [self.arrResult insertObject:dataSource.lastObject atIndex:0];
        [self.arrResult addObject:dataSource.firstObject];
    }
    [self.cvMain reloadData];
}

- (void)setIndexNow:(NSInteger)indexNow{
    if (indexNow > self.dataSource.count-1) {
        _indexNow = self.dataSource.count-1;
    }else{
        _indexNow = indexNow;
    }
    [self.cvMain setContentOffset:CGPointMake(self.pageWidth*(_indexNow+1), 0) animated:NO];
}
#pragma mark - Private
/**重置偏移量*/
- (void)resetContentOffset {
    self.cvMain.contentOffset = CGPointMake(self.pageWidth, 0);
}

/**
 根据 Cell 的索引计算出页数
 
 @param index  Cell 索引
 @return 页数
 */
- (int)pageIndexWithCellIndex:(NSInteger)index {
    
    return (int)index % self.dataSource.count;
}

/**
 获取当前索引
 */
- (int)currentIndex {
    
    int index = round(self.cvMain.contentOffset.x / self.pageWidth);
    index = index-1;
    if (index == -1){
        index = (int)self.dataSource.count - 1;
    }else if (index == self.dataSource.count){
        index = 0;
    }
    return MAX(0, index);
}

/**
 滑动到下一页或者上一页
 */
- (void)snapToPage {
    CGPoint pageOffset;
    pageOffset.x = [self pageOffsetForComponent:YES];
    pageOffset.y = [self pageOffsetForComponent:NO];
    CGPoint currentOffset = self.cvMain.contentOffset;
    if (!CGPointEqualToPoint(pageOffset, currentOffset)) {
        _snapping = YES;
        [self.cvMain setContentOffset:pageOffset animated:YES];
        WEAK_SELF;
        [STimeUtil delay:0.3 task:^{
            if (pageOffset.x/weakSelf.pageWidth == weakSelf.dataSource.count+1){
                [weakSelf.cvMain setContentOffset:CGPointMake(weakSelf.pageWidth, 0) animated:NO];
            }else if (pageOffset.x/weakSelf.pageWidth == 0){
                [weakSelf.cvMain setContentOffset:CGPointMake(weakSelf.pageWidth*(weakSelf.dataSource.count), 0) animated:NO];
            }
        }];
    }
    _dragVelocity = CGPointZero;
    _dragDisplacement = CGPointZero;
}
 
/**
 计算下一页或者上一页的偏移量
 */
- (CGFloat)pageOffsetForComponent:(BOOL)isX {
    
    if (((isX ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds)) == 0) || ((isX ? self.cvMain.contentSize.width : self.cvMain.contentSize.height) == 0))
        return 0;
    CGFloat pageLength = isX ? _pageWidth : _pageHeight; // 每页的宽度/高度
    if (pageLength < FLT_EPSILON) {
        pageLength = isX ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds);
    }
    pageLength *= self.cvMain.zoomScale; //
    
    CGFloat totalLength = isX ? self.cvMain.contentSize.width : self.cvMain.contentSize.height; // 可滚动范围
    CGFloat visibleLength = (isX ? CGRectGetWidth(self.bounds) : CGRectGetHeight(self.bounds)) * self.cvMain.zoomScale; // 当前显示宽度
    CGFloat currentOffset = isX ? self.cvMain.contentOffset.x : self.cvMain.contentOffset.y; // 当前偏移量
    CGFloat dragVelocity = isX ? _dragVelocity.x : _dragVelocity.y;
    CGFloat dragDisplacement = isX ? _dragDisplacement.x : _dragDisplacement.y;
    CGFloat newOffset;
    CGFloat index = currentOffset / pageLength;
    CGFloat lowerIndex = floorf(index);
    CGFloat upperIndex = ceilf(index);
    
    if (ABS(dragDisplacement) < DRAG_DISPLACEMENT_THRESHOLD || dragDisplacement * dragVelocity < 0) {
        if (index - lowerIndex > upperIndex - index) {
            index = upperIndex;
        } else {
            index = lowerIndex;
        }
    } else {
        if (dragVelocity > 0) {
            // 向左滑，下一页
            index = upperIndex;
        } else {
            // 向右滑，上一页
            index = lowerIndex;
        }
    }
    
    newOffset = pageLength * index;
    
    // 判断有没有超出范围
    if (newOffset > totalLength - visibleLength) {
        newOffset = totalLength - visibleLength;
    }
    if (newOffset < 0) {
        newOffset = 0;
    }
    return newOffset;
}


#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.arrResult.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    
    YMHomeHealthMoreItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    int index = [self pageIndexWithCellIndex:indexPath.item];
    if (index < self.arrResult.count) {
        cell.dict = [SDataUtil dictOf:self.arrResult[index]];
        cell.showSelect = [self currentIndex]+1==indexPath.item ? YES:NO;
    }
    return cell;
}

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if ([self.delegate respondsToSelector:@selector(cardView:didSelectedAtIndex:)]) {
        [self.delegate cardView:self didSelectedAtIndex:(indexPath.row % self.dataSource.count)];
    }
}


#pragma mark - UIScrollViewDelegate
/// 开始拖拽
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    _dragDisplacement = scrollView.contentOffset;
}

/// 停止拖拽
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate && self.pageEnable) {
        [self snapToPage];
    }
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    if (self.pageEnable) {
        *targetContentOffset = scrollView.contentOffset;
        _dragVelocity = velocity;
        _dragDisplacement = CGPointMake(scrollView.contentOffset.x - _dragDisplacement.x, scrollView.contentOffset.y - _dragDisplacement.y);
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (self.pageEnable){
        [self snapToPage];
    }
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (!_snapping && self.pageEnable) {
        [self snapToPage];
    } else {
        _snapping = NO;
    }
    if ([self.delegate respondsToSelector:@selector(cardView:changeCurrentIndex:)]) {
        [self.delegate cardView:self changeCurrentIndex:([self currentIndex])];
    }
    [self.cvMain reloadData];
}

#pragma mark - 懒加载
- (UICollectionView *)cvMain {
    if (_cvMain == nil) {
        _layout = [[YMHomeCycleFlowLayout alloc] init];
        _layout.maxWidth = [SFitUtil fit:233];
        _layout.maxHeight = [SFitUtil fit:102];
        _layout.itemHeight = [SFitUtil fit:102];
        _layout.itemWidth = [SFitUtil fit:233];
        _layout.spacing = [SFitUtil fit:25];
        self.pageWidth = _layout.itemWidth + _layout.spacing;
        _cvMain = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout];
        _cvMain.dataSource = self;
        _cvMain.delegate = self;
        _cvMain.showsHorizontalScrollIndicator = NO;
        _cvMain.backgroundColor = [UIColor clearColor];
        [_cvMain registerClass:[YMHomeHealthMoreItemCell class] forCellWithReuseIdentifier:cellIdentifier];
    }
    return _cvMain;
}
- (NSMutableArray *)arrResult{
    if (_arrResult == nil){
        _arrResult = [[NSMutableArray alloc] init];
    }
    return _arrResult;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
